﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Input;
using System.Drawing;
using OpenTK.Graphics;
using Common;

namespace T09.AssImp {
    class MyGameWindow : GameWindow {
        public MyGameWindow() {
            this.Load += MyGameWindow_Load;
            this.Resize += MyGameWindow_Resize;
            this.RenderFrame += MyGameWindow_RenderFrame;
            this.Unload += MyGameWindow_Unload;
            this.Width = 1280;
            this.Height = 720;

        }

        
        private void MyGameWindow_RenderFrame(object sender, FrameEventArgs e) {
            GL.ClearColor(.1f, .1f, .99f, .9f);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            Render();

            SwapBuffers();
            ProcessEvents();
        }
        Shader shader;
        Vao vao;
        //int textureId;
        Texture2D texture;
        List<ushort> indexList = new List<ushort>();
        List<Vector3> indexedVertexList = new List<Vector3>();
        List<Vector2> indexedUvList = new List<Vector2>();
        List<Vector3> indexedNormalList = new List<Vector3>();
        ushort[] indices;
        Vector3[] indexedVertices, indexedNormals;
        Vector2[] indexedUvs;
        Vbo<Vector3> vertexBuffer, normalBuffer;
        Vbo<Vector2> uvBuffer;
        Vbo<ushort> indexBuffer;
        VertexAttribManager attribs = new VertexAttribManager();
        private void MyGameWindow_Load(object sender, EventArgs e) {

            VSync = VSyncMode.Off;
            GL.Enable(EnableCap.DepthTest);
            GL.DepthFunc(DepthFunction.Less);
            GL.Enable(EnableCap.CullFace);
            vao = new Vao();
            shader = new Shader("shader.vs", "shader.fs");
            texture = Texture2D.Load("uvmap.dds");

            AssimpLoader.Load("suzanne.obj", indexList, indexedVertexList, indexedUvList, indexedNormalList);
            indices = indexList.ToArray();
            indexedVertices = indexedVertexList.ToArray();
            indexedUvs = indexedUvList.ToArray();
            indexedNormals = indexedNormalList.ToArray();

            vertexBuffer = new Vbo<Vector3>(indexedVertices);
            uvBuffer = new Vbo<Vector2>(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw, indexedUvs);
            normalBuffer = new Vbo<Vector3>(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw, indexedNormals);

            indexBuffer = new Vbo<ushort>(BufferTarget.ElementArrayBuffer, BufferUsageHint.StaticDraw, indices);

            attribs.AddAttrib(3, vertexBuffer);
            attribs.AddAttrib(2, uvBuffer);
            attribs.AddAttrib(3, normalBuffer);

        }

        private void Render() {

            shader.Use();
            InputControls.computeMatricesFromInput(this);
            var projection = InputControls.ProjectionMatrix;
            var view = InputControls.ViewMatrix;
            var model = Matrix4.Identity;
            var mvp = model * view * projection;
            shader.SetMatrix4("MVP", mvp);
            shader.SetMatrix4("M", model);
            shader.SetMatrix4("V", view);

            Vector3 lightPos = new Vector3(4, 4, 4);

            shader.SetVector3("LightPosition_worldspace", lightPos);

            //GL.ActiveTexture(TextureUnit.Texture0);
            //GL.BindTexture(TextureTarget.Texture2D, textureId);
            //shader.SetInt("myTextureSampler", 0);
            texture.Active((TextureUnit)(-int.MaxValue), shader, "myTextureSampler");
            //texture.Active(TextureUnit.Texture0, shader, "myTextureSampler");

            attribs.Enable();

            indexBuffer.Bind();
            GL.DrawElements(BeginMode.Triangles, indices.Length, DrawElementsType.UnsignedShort, 0);


            attribs.Disable();



        }

        private void MyGameWindow_Resize(object sender, EventArgs e) {
            GL.Viewport(0, 0, Width, Height);
        }



        private void MyGameWindow_Unload(object sender, EventArgs e) {
            GlDisposableObjectBase.DisposeObjects(shader, vao,vertexBuffer,uvBuffer,normalBuffer,indexBuffer,texture);
        }

    }
}
